package com.authstr.admin.service.impl;


import cn.hutool.core.util.StrUtil;
import com.authstr.admin.mapper.inter.DepartmentDao;
import com.authstr.admin.service.inter.DepartmentService;
import com.authstr.auth.constant.CacheKey;
import com.authstr.auth.constant.CacheName;
import com.authstr.auth.utils.EhcacheUntil;
import com.authstr.basic.exception.Assert;
import com.authstr.basic.exception.BaseExceptionEnum;
import com.authstr.basic.reqres.request.RequestPara;
import com.authstr.basic.reqres.utils.WebUtils;
import com.authstr.basic.web.service.BaseServiceImpl;
import com.authstr.model.base.BaseDepartment;
import com.authstr.model.constant.BaseC;
import com.authstr.model.utils.ModelUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;


@Service
public class DepartmentServiceImpl extends BaseServiceImpl<DepartmentDao, BaseDepartment> implements DepartmentService {

    @Autowired
    DepartmentDao departmentDao;

    @Override
    public Page query(@Param("page") Page page) {
        return departmentDao.query(page, WebUtils.getInteger("type_id"),WebUtils.get("name"));
    }

    @Override
    public List<Map> getAll(RequestPara para){
        return departmentDao.getAll(para.get("name"),para.get("exclude_id"));
    };

    /**
     * 添加或编辑
     * @param model
     */
    @Transactional(rollbackFor=Exception.class)
    @Override
    public void addOrEdit(BaseDepartment model, RequestPara para) {
        Assert.isTrue(super.isUnique(model,"code"),"单位编码不能重复");
        if(model.getStatus()==null){
            model.setStatus(BaseC.COMMON_STATUS_NORMAL);
        }

        //设置 parent_ids属性值和 level属性值
        setParentIds(model);

        if(ModelUtil.isNew(model)){
            super.saveOrUpdate(model);
        }else{
            BaseDepartment oldModel=super.getById(model.getId());

            //在进行修改时,更新子单位
            updataAllChildParentIdsForEdit(oldModel,model);
            super.updateIntact(model);
        }
    }


    /**
     * 设置一个单位的parent_ids属性和level属性
     * @param model
     */
    public void setParentIds(BaseDepartment model){
        Assert.isTrue(model!=null,BaseExceptionEnum.PARA_ERROR);
        BaseDepartment oldModel=super.getById(model.getId());
        Integer parent_id=model.getParent_id();

        //如果修改了父单位,验证设置的父对象是否合法,不能将自身的子对象设置为自己的父对象
        if(model.getParent_id()!=null){
            if(!ModelUtil.isNew(model)){
                Assert.isTrue(oldModel!=null,BaseExceptionEnum.PARA_ERROR);
                String old_parent_ids=oldModel.getParent_ids();
                List<BaseDepartment> Departments= departmentDao.getLikeParentIds(oldModel.getId());
                for(BaseDepartment Department:Departments){
                    Assert.isTrue(!Department.getId().equals(model.getParent_id()),"不能将自身的子单位设置为自己的父单位");
                }
            }
            //获取父单位的parent_ids
            BaseDepartment parentModel=super.getById(parent_id);
            Assert.isTrue(parentModel!=null,BaseExceptionEnum.PARA_ERROR);
            model.setParent_ids(parentModel.getParent_ids()+"["+model.getParent_id()+"],");

            //设置层级
            int level=0;
            if( parentModel.getLevel()!=null){
                level = parentModel.getLevel()+1;
            }
            model.setLevel(level);
        }else{
            model.setParent_ids("");
            model.setLevel(1);
        }
    }

    /**
     * 在修改后,更新所有子单位的结构
     * @param oldDepartment
     * @param newDepartment
     */
    public void updataAllChildParentIdsForEdit(BaseDepartment oldDepartment, BaseDepartment newDepartment){
        List<BaseDepartment> Departments= departmentDao.getLikeParentIds(oldDepartment.getId());
        String oldPcodesPrefix = oldDepartment.getParent_ids() + "[" + oldDepartment.getId() + "],";

        for(BaseDepartment Department:Departments){
            String oldPcodesSuffix = Department.getParent_ids().substring(oldPcodesPrefix.length());
            String Department_parent_ids = newDepartment.getParent_ids() + "[" + newDepartment.getId() + "]," + oldPcodesSuffix;

            Department.setParent_ids(Department_parent_ids);
            int level = StrUtil.count(Department_parent_ids, "[");
            Department.setLevel(level+1);
            super.updateById(Department);
        }
    }

    /**
     *在删除后,修改子单位的继承关系和层级
     * @param byDelete 被删除的单位
     */
    public void updataAllChildParentIdsForDelete(BaseDepartment byDelete){
        List<BaseDepartment> Departments= departmentDao.getLikeParentIds(byDelete.getId());
        for(BaseDepartment Department:Departments){
            String new_parent_ids=StrUtil.replace(Department.getParent_ids(),"["+byDelete.getId()+"]","");
            Department.setParent_ids(new_parent_ids);

            Department.setParent_id(byDelete.getParent_id());

            Department.setLevel(Department.getLevel()-1);
            super.updateById(Department);
        }
    }

    /**
     * 在删除后,删除子单位
     * @param byDelete 被删除的单位
     */
    public void deleteAllChild(BaseDepartment byDelete){
        List<BaseDepartment> Departments= departmentDao.getLikeParentIds(byDelete.getId());
        for(BaseDepartment Department:Departments){
            super.removeById(Department);
        }
    }

    /**
     * 删除（不包括子单位）
     * @param ids
     */
    @Transactional(rollbackFor=Exception.class)
    @Override
    public void delete(Long[] ids){
        Assert.isTrue(ids!=null, BaseExceptionEnum.PARA_ERROR);
        for(int i=0;i<ids.length;i++){
            Long id=ids[i];
            BaseDepartment baseDepartment=super.getById(id);
            Assert.isTrue(baseDepartment!=null,BaseExceptionEnum.PARA_ERROR);
            updataAllChildParentIdsForDelete(baseDepartment);
            Assert.isTrue(super.removeById(id),"第"+(i+1)+"条数据删除失败!本次操作无效");

        }
    }

    /**
     * 删除,包括子单位
     * @param ids
     */
    @Transactional(rollbackFor=Exception.class)
    @Override
    public void deleteChildren(Long[] ids){
        Assert.isTrue(ids!=null, BaseExceptionEnum.PARA_ERROR);
        for(int i=0;i<ids.length;i++){
            Long id=ids[i];
            BaseDepartment baseDepartment=super.getById(id);
            Assert.isTrue(baseDepartment!=null,BaseExceptionEnum.PARA_ERROR);
            deleteAllChild(baseDepartment);
            Assert.isTrue(super.removeById(id),"第"+(i+1)+"条数据删除失败!本次操作无效");
        }
    }
    


}
